//////////////////////////////////////////////////////////////////////////

#ifndef _ASYNCCALLER_H_
#define _ASYNCCALLER_H_

//////////////////////////////////////////////////////////////////////////

#include <boost/system/error_code.hpp>
#include <boost/function.hpp>
#include <vector>

//////////////////////////////////////////////////////////////////////////


/** Asynchronous function caller
*
*  @author   Roman Pasechnik
*  @since    Jul 27th, 2009
*  @updated  Nov 20th, 2009
*/
class AsyncCaller
{
//////////////////////////////////////////////////////////////////////////

public:

//////////////////////////////////////////////////////////////////////////


    /** Destructor */
    ~AsyncCaller();


//////////////////////////////////////////////////////////////////////////


    /** [Utility type]: Pointer to function that have to be asynchronously called */
    typedef boost::function<void (int _param)> UserFunction;


    /** Asynchronously call the desired function. */
    void AsyncCall( UserFunction _function, int _param, size_t _delay = 0 );


//////////////////////////////////////////////////////////////////////////

private:

//////////////////////////////////////////////////////////////////////////


    /** [Utility type]: Set of pointers to deadline timers */
    typedef std::vector<void*> DeadlineTimerVec;


    /** Pointer to boost::asio::deadline_timer object */
    DeadlineTimerVec m_DeadlineTimerVec;


//////////////////////////////////////////////////////////////////////////


    /** Delete all timers */
    void DeleteDeadlineTimers();


    /** Get free deadline timer. If all timers are busy, create a new one */
    void* GetFreeDeadlineTimer();


    /** Create a new deadline timer and add it to collection */
    void* AddNewTimer();


    /** Internal handler, checking for errors */
    void HandleCall( const boost::system::error_code& _error,
                     UserFunction _function,
                     int _param );


//////////////////////////////////////////////////////////////////////////
};


//////////////////////////////////////////////////////////////////////////

#endif

//////////////////////////////////////////////////////////////////////////
